package com.mini.core.dao;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.druid.sql.visitor.functions.Char;
import com.mini.core.BaseEntity;
import com.mini.core.MiniDaoException;
import com.mini.core.PageResult;
import com.mini.core.grammar.DbProducer;
import com.mini.core.grammar.Record;
import com.mini.core.utils.MiniUtil;

/**
 * 通用Dao对象
 * @author sxjun
 * 2016-1-15
 */
public class MiniDao implements IMiniDao
{
    private DbProducer dbProducer;

    public void setDbProducer(DbProducer dbProducer) {
        this.dbProducer = dbProducer;
    }
    
    /**
     * 插入数据
     * @param record BaseEntity或Record对象 <必须继承Record>
     * @return int
     */
    public <T extends Record> int insert(T record){
    	return dbProducer.save(record);
    }

    /**
     * 删除数据
     * @param record BaseEntity或Record对象 <必须继承Record>
     * @return int
     */
    public <T extends Record> int delete(T record){
    	return dbProducer.delete(record);
    }
    
    /**
     * 删除数据
     * @param clazz BaseEntity或Record对象 <必须继承Record>
     * @param primaryKey 主键
     * @return int
     */
    public int deleteById(Class<? extends BaseEntity> clazz, Object primaryKey){
    	return dbProducer.deleteById(clazz, primaryKey);
    }
    
    /**
     * 更新数据
     * @param record BaseEntity或Record对象 <必须继承Record>
     * @return int
     */
    public <T extends Record> int update(T record){
    	return dbProducer.update(record);
    }
    
    /**
     * 执行sql语句
     * @param sql 执行语句
     * @param paras 参数
     * @return int
     */
    public int execute(String sql, Object... paras){
    	return dbProducer.update(sql, paras);
    }
    
    /**
     * 根据ID查找单个实体
     * @param clazz  类<必须继承BaseEntity>
     * @param primaryKey 主键
     * @return T extends BaseEntity
     */
    @SuppressWarnings("unchecked")
	public <T extends BaseEntity> T findById(Class<? extends BaseEntity> clazz, Object primaryKey){
    	return (T) dbProducer.findById(clazz, primaryKey);
    }

    /**
     * 查找单条记录
     * @param sql 查询语句
     * @param clazz 可以是[Record.class(弱类型);BaseEntity.class(强类型)，或基本类型[String、Integer(int)、Long(long)、Char(char)、Double(double)、Float(float)、Short(short)、Boolean(boolean)、Byte(byte)]
     * @param args 参数值数组
     * @return T {String、Integer、Long、Record、BaseEntity等}
     */
    @SuppressWarnings("unchecked")
	public <T> T find(String sql, Class clazz, Object... args){
    	if(clazz.isPrimitive()
    			||String.class.equals(clazz)
    			||Integer.class.equals(clazz)
    			||Double.class.equals(clazz)
    			||Float.class.equals(clazz)
    			||Long.class.equals(clazz)
    			||Short.class.equals(clazz)
    			||Boolean.class.equals(clazz)
    			||Byte.class.equals(clazz)
    			||Char.class.equals(clazz))
    		return (T) dbProducer.queryForObject(sql,clazz,args);
    	else if(MiniUtil.isBaseEntity(clazz))
    		return (T) dbProducer.findFirst(sql,clazz,args);
    	else if(MiniUtil.isRecord(clazz))
    		return (T) dbProducer.findFirst(sql,args);
    	else
    		throw new MiniDaoException("只支持基本类型[String、Integer(int)、Long(long)、Char(char)、Double(double)、Float(float)、Short(short)、Boolean(boolean)、Byte(byte)]和以[Record.class(弱类型);BaseEntity.class(强类型)]为基类的对象转换;不支持("+clazz.getSimpleName()+")类型的转换。");
    }

    /**
     * 查找一个list
     * @param sql 查询语句
     * @param clazz 可以是[Record.class(弱类型);BaseEntity.class(强类型)] 或 基本类型[String、Integer(int)、Long(long)、Char(char)、Double(double)、Float(float)、Short(short)、Boolean(boolean)、Byte(byte)]
     * @param args 参数值数组
     * @return T extends BaseEntity
     */
    @SuppressWarnings("unchecked")
	public <T extends Record> List<T> findList(String sql, Class clazz, Object... args){
    	if(clazz.isPrimitive()
    			||String.class.equals(clazz)
    			||Integer.class.equals(clazz)
    			||Double.class.equals(clazz)
    			||Float.class.equals(clazz)
    			||Long.class.equals(clazz)
    			||Short.class.equals(clazz)
    			||Boolean.class.equals(clazz)
    			||Byte.class.equals(clazz)
    			||Char.class.equals(clazz))
    		return dbProducer.queryForList(sql, clazz, args);
    	else if(MiniUtil.isBaseEntity(clazz))
    		return dbProducer.findEntity(sql,clazz,args);
    	else  if(MiniUtil.isRecord(clazz))
    		return (List<T>) dbProducer.find(sql, args);
    	else
    		throw new MiniDaoException("只支持基本类型[String、Integer(int)、Long(long)、Char(char)、Double(double)、Float(float)、Short(short)、Boolean(boolean)、Byte(byte)]和以[Record.class(弱类型);BaseEntity.class(强类型)]为基类的对象转换;不支持("+clazz.getSimpleName()+")类型的转换。");
    }
    
    /**
     * 分页查找一个list
     * @param sql 查询语句
     * @param pageNumber 记录行的偏移量
     * @param pageSize 记录行的最大数目
     * @param clazz 可以是[Record.class(弱类型);BaseEntity.class(强类型)]，或基本类型[String、Integer(int)、Long(long)、Char(char)、Double(double)、Float(float)、Short(short)、Boolean(boolean)、Byte(byte)]
     * @param args 参数值数组
     * @return T extends BaseEntity
     */
    @SuppressWarnings("unchecked")
	public <T> List<T> paginate(String sql,int pageNumber, int pageSize, Class clazz, Object... args){
    	if(clazz.isPrimitive()
    			||String.class.equals(clazz)
    			||Integer.class.equals(clazz)
    			||Double.class.equals(clazz)
    			||Float.class.equals(clazz)
    			||Long.class.equals(clazz)
    			||Short.class.equals(clazz)
    			||Boolean.class.equals(clazz)
    			||Byte.class.equals(clazz)
    			||Char.class.equals(clazz)){
    		List<T> list = new ArrayList<T>();
    		List<Record> records = dbProducer.paginateRecord(pageNumber, pageSize, sql, args);
    		for(Record record : records){
    			Object[] o = record.getColumnValues();
    			list.add((T)o[0]);
    			break;
    		}
    		return list;
    	}else if(MiniUtil.isBaseEntity(clazz))
    		return dbProducer.paginateEntity(pageNumber, pageSize, clazz, sql, args);
    	else  if(MiniUtil.isRecord(clazz))
    		return (List<T>) dbProducer.paginateRecord(pageNumber, pageSize, sql, args);
    	else
    		throw new MiniDaoException("只支持基本类型[String、Integer(int)、Long(long)、Char(char)、Double(double)、Float(float)、Short(short)、Boolean(boolean)、Byte(byte)]和以[Record.class(弱类型);BaseEntity.class(强类型)]为基类的对象转换;不支持("+clazz.getSimpleName()+")类型的转换。");
    }
    
    /**
     * 获取分页Record数据
     * @param pageNumber 记录行的偏移量
     * @param pageSize 记录行的最大数目
     * @param sql 执行语句
     * @param clazz 可以是[Record.class(弱类型);BaseEntity.class(强类型)]，或基本类型[String、Integer(int)、Long(long)、Char(char)、Double(double)、Float(float)、Short(short)、Boolean(boolean)、Byte(byte)]
     * @param args 参数
     * @return PageResult<Record>
     */
    @SuppressWarnings("unchecked")
	public <T> PageResult<T> paginateResult(String sql, int pageNumber, int pageSize, Class clazz, Object... args){
    	if(clazz.isPrimitive()
    			||String.class.equals(clazz)
    			||Integer.class.equals(clazz)
    			||Double.class.equals(clazz)
    			||Float.class.equals(clazz)
    			||Long.class.equals(clazz)
    			||Short.class.equals(clazz)
    			||Boolean.class.equals(clazz)
    			||Byte.class.equals(clazz)
    			||Char.class.equals(clazz)){
    		PageResult<Record> records = dbProducer.paginate(pageNumber, pageSize, sql, args);
    		List<T> list = new ArrayList<T>();
    		for(Record record : records.getResults()){
    			Object[] o = record.getColumnValues();
    			list.add((T)o[0]);
    			break;
    		}
    		PageResult<T> reds = new PageResult<T>(list, pageNumber, pageSize, Integer.parseInt(String.valueOf(records.getResultCount())));
    		return reds;
    	}else if(MiniUtil.isBaseEntity(clazz))
    		return dbProducer.paginate(pageNumber, pageSize, sql, clazz, args);
    	else  if(MiniUtil.isRecord(clazz))
    		return (PageResult<T>) dbProducer.paginate(pageNumber, pageSize, sql, args);
    	else
    		throw new MiniDaoException("只支持基本类型[String、Integer(int)、Long(long)、Char(char)、Double(double)、Float(float)、Short(short)、Boolean(boolean)、Byte(byte)]和以[Record.class(弱类型);BaseEntity.class(强类型)]为基类的对象转换;不支持("+clazz.getSimpleName()+")类型的转换。");
    }
}
